﻿using ProtoBuf;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace McsUtility
{
    public enum ClientType : byte
    {
        Unknown = 0,
        MinerClient = 1,
        AdminClient = 2,
        AppClient = 3,
    }

    public enum ProtoType : byte
    {
        Unknown = 0,
        NodeServerRequestConnId = 1,
        CommServerResponseConnId = 2,
        MinerClientConnect = 3,
        MinerClientDisConnect = 4,
        MinerClientLogin = 5,//矿工登录NodeServer
        NodeServerClientLogin = 6,//NodeServer回应矿工登录
        MinerManagerLogin = 7,//管理端登录NodeServer
        NodeServerManagerLogin = 8,//NodeServer回应管理端登录
        MinerManagerGetRegSmsCode = 9,//管理端申请注册验证码
        NodeServerManagerGetRegSmsCode = 10,//NodeServer回应管理端申请注册验证码
        MinerManagerReg = 11,//管理端提交注册信息
        NodeServerManagerReg = 12,//NodeServer回应管理端提交注册信息
        MinerManagerGetCurrencysInfo = 13,//管理端提交获取币种请求
        NodeServerManagerGetCurrencysInfo = 14,//NodeServer回应管理端获取币种请求
        MinerLoginCommServer = 15,//管理端登录通知CommServer
        MinerManagerAddWallets = 16,//管理端添加钱包
        MinerManagerDelWallets = 17,//管理端删除钱包
        MinerManagerAddOrePools = 18,//管理端添加矿池
        MinerManagerDelOrePools = 19,//管理端删除矿池
        NodeServerManagerAddWallets = 20,//NodeServer回应管理端添加钱包
        NodeServerManagerDelWallets = 21,//NodeServer回应管理端删除钱包
        NodeServerManagerAddOrePools = 22,//NodeServer回应管理端添加矿池
        NodeServerManagerDelOrePools = 23,//NodeServer回应管理端删除矿池
        MinerManagerModifyWallets = 24,//管理端修改钱包
        MinerManagerModifyOrePools = 25,//管理端修改矿池
        NodeServerManagerModifyWallets = 26,//NodeServer回应管理端修改钱包
        NodeServerManagerModifyOrePools = 27,//NodeServer回应管理端修改矿池
        MinerManagerGetMiners = 28,//管理端请求的矿机搜索信息
        NodeServerManagerGetMiners = 29,//NodeServer回应管理端请求的矿机搜索信息
        MinerManagerModifyOrePoolUrl = 30,//修改矿池（高级配置）
        MinerManagerStartMining = 31,//开始挖矿
        MinerManagerEndMining = 32,//停止挖矿
        MinerManagerReset = 33,//重启机器
        MinerManagerModifyOrePoolUrlCommServer = 34,//修改矿池转到CommServer（高级配置）
        MinerManagerStartMiningCommServer = 35,//开始挖矿转到CommServer
        MinerManagerEndMiningCommServer = 36,//停止挖矿转到CommServer
        MinerManagerResetCommServer = 37,//重启机器转到CommServer
        CommServerMinerManagerModifyOrePoolUrl = 38,//CommServer下发修改矿池指令（高级配置）
        CommServerMinerManagerStartMining = 39,//CommServer下发开始挖矿指令
        CommServerMinerManagerEndMining = 40,//CommServer下发停止挖矿指令
        CommServerMinerManagerReset = 41,//CommServer下发重启机器指令
        NodeServerMinerManagerModifyOrePoolUrl = 42,//NodeServer下发修改矿池指令（高级配置）
        NodeServerMinerManagerStartMining = 43,//NodeServer下发开始挖矿指令
        NodeServerMinerManagerEndMining = 44,//NodeServer下发停止挖矿指令
        NodeServerMinerManagerReset = 45,//NodeServer下发重启机器指令
        MinerClientStartMining = 46,//矿机提交挖矿状态
        MinerClientSendData = 47,//矿机提交挖矿信息
        MinerClientStopMining = 48,//矿机提交停止挖矿状态
        MinerCloseCommServer = 49,//管理端掉线通知CommServer
        GetNodeServerCommServer = 50,//向CommServer询问可连接NodeServer
        CommServerGetNodeServer = 51,//CommServer响应询问可连接NodeServer
        MinerReAccept = 52,//NodeServer通知端重连NodeServer
        MinerManagerGetRedisData = 53,//管理端请求Redis数据
        NodeServerMinerManagerGetRedisData = 54,//NodeServer响应管理端请求Redis数据
        CommServerMinerLoginToNodeServer = 55,//CommonServer下发矿机登录信息给NodeServer
        NodeServerMinerLoginToManager = 56,//NodeServer下发矿机登录信息给管理端
        CommServerMinerLogoutToNodeServer = 57,//CommServer下发矿机离线信息给NodeServer
        NodeServerMinerLogoutToManager = 58,//NodeServer下发矿机离线信息给管理端
        MinerClientStartMiningToCommServer = 59,//矿机挖矿状态发送给CommServer
        MinerClientStartMiningToNodeServer = 60,//矿机挖矿状态下发给NodeServer
        MinerClientStartMiningToManager = 61,//矿机挖矿状态下发给管理端
        MinerManagerModifyBatch = 62,//批量修改矿池
        MinerManagerModifyBatchCommServer = 63,//批量修改矿池转到CommServer
        CommServerMinerManagerModifyBatch = 64,//CommServer下发批量修改矿池指令
        NodeServerMinerManagerModifyBatch = 65,//NodeServer下发批量修改矿池指令
        AppManagerLogin = 66,//APP端登录
        NodeServerInfoToCommServer = 67,//NodeServer通知CommServerIP信息
        MinerClientEndMiningToCommServer = 68,//矿机挖矿状态发送给CommServer
        MinerClientEndMiningToNodeServer = 69,//矿机挖矿状态下发给NodeServer
        MinerClientEndMiningToManager = 70,//矿机挖矿状态下发给管理端
        MinerManagerDownToNodeServer = 71,//管理端已经登录，发送NodeServer响应管理端的ConnId
        MinerManagerDownToManager = 72,//管理端收到指令，断开连接
        MinerManagerDelMiner = 73,//删除矿机
        NodeServerMinerManagerDelMiner = 74,//删除矿机
        MinerCloseToNodeServerr = 75,//掉线通知NodeServer
        MinerManagerGetRePassSmsCode = 76, //管理端申请修改密码验证码
        NodeServerManagerGetRePassSmsCode = 77,//NodeServer回应管理端申请修改密码验证码
        MinerManagerRePass = 78,//管理端提交修改密码信息
        NodeServerManagerRePass = 79,//NodeServer回应管理端提交修改密码信息
        MinerManagerAddRemark = 80,//管理端添加备注
        NodeServerManagerAddRemark = 81,//NodeServer回应管理端添加备注
        MinerManagerDelRemark = 82,//管理端删除备注
        NodeServerManagerDelRemark = 83,//NodeServer回应管理端删除备注
        MinerManagerModifyRemark = 84,//管理端修改备注
        NodeServerManagerModifyRemark = 85,//NodeServer回应管理端修改备注
        MinerClientWarnToNodeServer = 86,//矿工提交报警
        NodeServerWarnToCommServer = 87,//报警转交CommServer
        CommServerWarnToNodeServer = 88,//CommServer下发报警信息
        NodeServerWarnToMinerManager = 88,//NodeServer下发报警信息
        MinerManagerGetMinerModel = 89,//管理端请求的矿机搜索信息
        NodeServerManagerGetMinerModel = 90,//NodeServer回应管理端请求的矿机搜索信息
        MinerClientHeartbeat = 91,//心跳
        MinerManagerGetLogs = 92,//获得日志
        NodeServerMinerManagerGetLogs = 93,//响应获得日志
        MinerManagerGetStaffs = 94,//获取业务员
        NodeServerMinerManagerGetStaffs = 95,//NodeServer响应获取业务员
        MinerManagerReStaff=96,//修改业务员
        NodeServerMinerManagerReStaff=97,//NodeServer响应修改业务员
        MinerManagerGetMinersAll = 98,//管理端请求的矿机搜索信息
        NodeServerManagerGetMinersAll = 99,//NodeServer回应管理端请求的矿机搜索信息

    }
    public class ProtocolHelper
    {
        public static byte[] WritePackage(ProtoType pType, byte[] data)
        {
            var bytes = new byte[data.Length + 1];
            bytes[0] = (byte)pType;
            Array.Copy(data, 0, bytes, 1, data.Length);
            return bytes;
        }
        public static byte[] WritePackage(ProtoType pType, int data)
        {
            var bytes = System.BitConverter.GetBytes(data);
            return WritePackage(pType, bytes);
        }

        public static byte[] WritePackage(ProtoType pType, IntPtr data)
        {
            return WritePackage(pType, (int)data);
        }

        public static byte[] WritePackage(ProtoType pType, string data)
        {
            var bytes = Encoding.UTF8.GetBytes(data);
            return WritePackage(pType, bytes);
        }

        public static byte[] WritePackage<T>(ProtoType pType, T data)
        {
            var json = TomNet.Utility.Data.JsonHelper.ToJson(data);
            return WritePackage(pType, json);
        }



        public static ProtoType GetProtoType(byte[] package, out byte[] body)
        {
            if (package.Length > 1)
            {
                body = new byte[package.Length - 1];
                Array.Copy(package, 1, body, 0, body.Length);
            }
            else
            {
                body = null;
            }
            return (ProtoType)package[0];
        }

        public static T ReadPackageBody<T>(byte[] body)
        {
            var json = Encoding.UTF8.GetString(body);
            return TomNet.Utility.Data.JsonHelper.FromJson<T>(json);
        }
        public static string ReadPackageBody(byte[] body)
        {
            return Encoding.UTF8.GetString(body);
        }


    }


    public class ProtoBufHelper
    {
        public static byte[] SerializeBytes<T>(T obj)
        {
            using (var stream = new MemoryStream())
            {
                Serializer.Serialize(stream, obj);
                return stream.ToArray();
            }
        }
        public static T Deserialize<T>(byte[] bytes)
        {
            using (MemoryStream ms = new MemoryStream(bytes))
            {
                T t = Serializer.Deserialize<T>(ms);
                return t;
            }
        }

        public static string SerializeStr<T>(T obj)
        {
            using (MemoryStream ms = new MemoryStream())
            {
                Serializer.Serialize<T>(ms, obj);
                return Encoding.UTF8.GetString(ms.ToArray());
            }
        }

        public static T Deserialize<T>(string content)
        {
            using (MemoryStream ms = new MemoryStream(Encoding.UTF8.GetBytes(content)))
            {
                T t = Serializer.Deserialize<T>(ms);
                return t;
            }
        }
    }

}
